<template>
  <div>
    <div>
      <div id="container" style="height: 100%;"></div>
    </div>
  </div>
</template>

<script lang="ts">
import G6 from '@antv/g6'
import { Vue, Component, Prop } from 'vue-property-decorator'

@Component({})
export default class MyDecisionTree extends Vue {
  @Prop({ type: Object, default: () => ({}) }) leafs!: any

  public mounted() {
    // const colors: any = {
    //   B: '#5B8FF9',
    //   R: '#F46649',
    //   Y: '#EEBC20',
    //   G: '#5BD8A6',
    //   DI: '#A7A7A7',
    // }
    this.registerFn()
    this.initGraph()
  }

  // 自定义节点、边
  public registerFn() {
    /**
     * 自定义节点
     */
    G6.registerNode(
      'flow-rect',
      {
        shapeType: 'flow-rect',
        draw(cfg: any, group: any) {
          const {
            // name,
            // variableName,
            // variableValue,
            // variableUp,
            // label,
            collapsed,
            feature,
            threshold,
            // currency,
            // status,
            // rate,
          } = cfg
          const grey = '#CED4D9'
          // 逻辑不应该在这里判断
          const rectConfig = {
            width: 142,
            height: 44,
            lineWidth: 1,
            fontSize: 12,
            fill: '#fff',
            radius: 4,
            stroke: grey,
            opacity: 1,
          }

          const nodeOrigin = {
            x: -rectConfig.width / 2,
            y: -rectConfig.height / 2,
          }

          const textConfig = {
            textAlign: 'left',
            textBaseline: 'bottom',
          }

          const rect = group?.addShape('rect', {
            attrs: {
              x: nodeOrigin.x,
              y: nodeOrigin.y,
              ...rectConfig,
            },
          })

          const rectBBox = rect?.getBBox()

          // price
          const label = `${feature}${threshold}`
          const price: any = group?.addShape('text', {
            attrs: {
              ...textConfig,
              x: 12 + nodeOrigin.x,
              y: rectBBox.maxY - 12,
              text: label.length > 13 ? `${label.slice(0, 13)}...` : label,
              fontSize: 16,
              fontFamily: 'Helvetica-Bold, Helvetica',
              fill: '#373B52',
              opacity: 0.85,
            },
            name: 'name-shape',
          })

          // label currency
          group?.addShape('text', {
            attrs: {
              ...textConfig,
              x: price.getBBox().maxX + 5,
              y: rectBBox.maxY - 12,
              // text: threshold,
              fontSize: 16,
              fill: '#373B52',
              opacity: 0.75,
            },
            name: 'name-shape',
          })

          // collapse rect
          if (cfg?.children?.length > 0) {
            group?.addShape('rect', {
              attrs: {
                x: rectConfig.width / 2 - 8,
                y: -8,
                width: 16,
                height: 16,
                stroke: 'rgba(0, 0, 0, 0.25)',
                cursor: 'pointer',
                fill: '#fff',
              },
              name: 'collapse-close',
              modelId: cfg?.id,
            })

            // collpase text
            group?.addShape('text', {
              attrs: {
                x: rectConfig.width / 2,
                y: -1,
                textAlign: 'center',
                textBaseline: 'middle',
                text: collapsed ? '+' : '-',
                fontSize: 16,
                cursor: 'pointer',
                fill: 'rgba(0, 0, 0, 0.25)',
              },
              name: 'collapse-open',
              modelId: cfg?.id,
            })
          }
          // @ts-ignore
          this.drawLinkPoints(cfg, group)
          return rect
        },
        update(cfg, item) {
          const group = item.getContainer()
          // @ts-ignore
          this.updateLinkPoints(cfg, group)
        },
        setState(name, value, item) {
          if (name === 'collapse') {
            const group = item?.getContainer()
            const collapseText = group?.find(
              (elment: any) => elment.get('name') === 'collapse-open'
            )
            if (collapseText) {
              if (!value) {
                collapseText.attr({
                  text: '-',
                })
              } else {
                collapseText.attr({
                  text: '+',
                })
              }
            }
          }
        },
        getAnchorPoints() {
          return [
            [0, 0.5],
            [1, 0.5],
          ]
        },
      },
      'rect'
    )

    G6.registerEdge(
      'flow-cubic',
      {
        getControlPoints(cfg: any) {
          let { controlPoints } = cfg
          // let controlPoints = cfg.controlPoints// 指定controlPoints
          if (!controlPoints || controlPoints.length === 0) {
            const { startPoint, endPoint, sourceNode, targetNode } = cfg
            const {
              x: startX,
              y: startY,
              coefficientX,
              coefficientY,
            } = sourceNode ? sourceNode.getModel() : startPoint
            const { x: endX, y: endY } = targetNode
              ? targetNode.getModel()
              : endPoint
            let curveStart = (endX - startX) * coefficientX
            let curveEnd = (endY - startY) * coefficientY
            curveStart = curveStart > 40 ? 40 : curveStart
            curveEnd = curveEnd < -30 ? curveEnd : -30
            controlPoints = [
              { x: startPoint.x + curveStart, y: startPoint.y },
              { x: endPoint.x + curveEnd, y: endPoint.y },
            ]
          }
          return controlPoints
        },
        getPath(points: any) {
          const path = []
          path.push(['M', points[0].x, points[0].y])
          path.push([
            'C',
            points[1].x,
            points[1].y,
            points[2].x,
            points[2].y,
            points[3].x,
            points[3].y,
          ])
          return path
        },
      },
      'single-line'
    )
  }

  public initGraph() {
    //  组件props
    const properties = {
      data: this.leafs,
      config: {
        padding: [20, 50],
        defaultLevel: 3,
        defaultZoom: 0.8,
        modes: { default: ['zoom-canvas', 'drag-canvas'] },
      },
    }

    const container = document.querySelector('#container')
    const width = container?.scrollWidth
    const height = container?.scrollHeight || 800

    // const descriptionDiv = document.createElement('button')
    // descriptionDiv.innerHTML = '一键展开'
    // container?.appendChild(descriptionDiv)
    // 默认配置
    const defaultConfig = {
      width,
      height,
      modes: {
        default: ['zoom-canvas', 'drag-canvas'],
      },
      fitView: true,
      animate: true,
      defaultNode: {
        type: 'flow-rect',
      },
      defaultEdge: {
        type: 'cubic-horizontal',
        style: {
          stroke: '#CED4D9',
        },
      },
      layout: {
        type: 'indented',
        direction: 'LR',
        dropCap: false,
        indent: 300,
        getHeight: () => {
          return 60
        },
      },
    }
    const { data } = properties
    let graph: any = null
    if (!data) {
      return
    }
    const { config } = properties
    // const { onInit, config } = properties
    const tooltip = new G6.Tooltip({
      // offsetX and offsetY include the padding of the parent container
      offsetX: 20,
      offsetY: 30,
      // the types of items that allow the tooltip show up
      // 允许出现 tooltip 的 item 类型
      itemTypes: ['node'],
      // custom the tooltip's content
      // 自定义 tooltip 内容
      getContent: (element: any) => {
        const outDiv = document.createElement('div')
        outDiv.style.padding = '2px'
        outDiv.style.fontSize = '14px'
        const nodeName = `${element.item.getModel().feature}${
          element.item.getModel().threshold
        }`
        outDiv.innerHTML = `${nodeName}`
        return outDiv
      },
      shouldBegin: (element: any) => {
        if (element.target.get('name') === 'name-shape') {
          return true
        }
        return false
      },
    })
    graph = new G6.TreeGraph({
      container: 'container',
      ...defaultConfig,
      ...config,
      plugins: [tooltip],
    })
    // if (typeof onInit === 'function') {
    //   onInit(graph)
    // }
    graph.data(data)
    graph.render()
    this.$emit('finish-render')
    graph.zoom(config.defaultZoom || 1)

    // const fatherNode = graph.findById(graph.cfg.nodes[0]._cfg.id)
    // let sortByCombo = fatherNode.getModel().collapsed
    // descriptionDiv.addEventListener('click', () => {
    //   sortByCombo = !sortByCombo
    //   descriptionDiv.innerHTML = sortByCombo ? '一键展开' : '一键收起'

    //   const nodeModel = fatherNode.getModel()
    //   nodeModel.collapsed = !nodeModel.collapsed
    //   graph.layout()
    //   graph.setItemState(fatherNode, 'collapse', nodeModel.collapsed)
    // })

    const handleCollapse = (element: any) => {
      const { target } = element
      const id = target.get('modelId')
      const item = graph.findById(id)
      const nodeModel = item.getModel()
      nodeModel.collapsed = !nodeModel.collapsed
      graph.layout()
      graph.setItemState(item, 'collapse', nodeModel.collapsed)

      // if (nodeModel.name === 0) {
      //   sortByCombo = nodeModel.collapsed
      //   descriptionDiv.innerHTML = sortByCombo ? '一键展开' : '一键收起'
      // }
    }
    graph.on('collapse-open:click', (element: any) => {
      handleCollapse(element)
    })
    graph.on('collapse-close:click', (element: any) => {
      handleCollapse(element)
    })

    if (typeof window !== 'undefined') {
      document.addEventListener('onresize', function () {
        if (!graph || graph.get('destroyed')) {
          return
        }
        if (!container || !container.scrollWidth || !container.scrollHeight) {
          return
        }
        graph.changeSize(container.scrollWidth, container.scrollHeight - 30)
      })
    }
  }
}
</script>
